package com.fingard.dsp.bank.directbank.allinpay02;

import com.allinpay.ets.client.SecurityUtil;
import com.fingard.common.utils.json.JSONUtils;
import com.fingard.constant.Format;
import com.fingard.crypto.DigestHelper;
import com.fingard.crypto.SignVerifyHelper;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.SendBankRespose;
import com.fingard.dsp.bank.directbank.allinpay02.util.AIPGSignature;
import com.fingard.dsp.bank.directbank.allinpay02.util.HttpConnectionUtil;
import com.fingard.dsp.bank.directbank.allinpay02.util.HttpUtil;
import com.fingard.dsp.bank.directbank.allinpay02.util.SybUtil;
import com.fingard.dsp.bank.reqrespobj.statement.ReqQryStatement;
import com.fingard.net.WebRequest;
import com.fingard.net.https.HttpsHandler;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.util.SortHelper;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static com.fingard.dsp.bank.directbank.allinpay02.util.AppUtil.md5;


public class AllInPay02Base extends DirectBase {
    private static TransIDHelper idHelper = new TransIDHelper(1, 9999);

    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected String getCharset(String p_def, String p_for) {
        return getBankConfig().getCharset(p_def, p_for);
    }

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    /**
     * 生成随机字符串
     *
     * @return
     * @throws Exception
     */
    protected String get_nonce_str() throws Exception {
        String time_stamp = DateHelper.getSecsFrom1970();
        //随机字符串 String(32)
        Random random = new Random();
        long randLong = random.nextLong();
        randLong = random.nextLong();
        String nonce_str = time_stamp + String.format("%20d", randLong);
        nonce_str = DigestHelper.cryptoMD5RetHexStr(nonce_str.getBytes());
        return nonce_str;
    }

    protected HashMap<String, String> getOpenid(String p_appId, String p_appSecret, String p_code) {
        HashMap<String, String> retHash = new HashMap<String, String>();
        String respCode = "";
        String respInfo = "";
        String tmpUrl = bankFront.getUrl("access_token");
        if (StringHelper.isNullOrEmpty(tmpUrl)) {
            respCode = "-1";
            respInfo = "未设置“通过code换取网页授权access_token”的地址";
        } else {
            tmpUrl = tmpUrl + "?appid=" + p_appId + "&secret=" + p_appSecret + "&code=" + p_code + "&grant_type=authorization_code";
            this.WriteBankLogStep2(tmpUrl);
            WebRequest tmpWebRequest = new WebRequest(tmpUrl);
            String[] tmpRet = tmpWebRequest.upload(null, this.getCharset());
            if (tmpRet[0].length() == 0) {
                this.WriteBankLogStep3(tmpRet[1]);
                if (tmpRet[1].startsWith("{")) {
                    retHash = JSONUtils.json2Map(tmpRet[1]);
                    respCode = "0";
                } else {
                    respCode = "-1";
                    respInfo = tmpRet[1];
                }
            } else {
                this.WriteBankLogLn(tmpRet[0] + "\r\n" + tmpRet[1]);
                respCode = "-1";
                respInfo = tmpRet[1];
            }
        }
        retHash.put("RespCode", respCode);
        retHash.put("RespInfo", respInfo);
        return retHash;
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("INFO");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        xmlWriter.writeElementString("VERSION", "03");
        xmlWriter.writeElementString("DATA_TYPE", "2");
        xmlWriter.writeElementString("LEVEL", "5");

        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("USER_PASS", actItem.userFlag);

        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        //xmlWriter.writeElementClosed("SIGNED_MSG");
        xmlWriter.writeEndElement();//</INFO>
    }

    protected void writeAgrmCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("INFO");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        if ("300005".equals(bankHeader.TRX_CODE) || "300003".equals(bankHeader.TRX_CODE) || "340009".equals(bankHeader.TRX_CODE) || "310016".equals(bankHeader.TRX_CODE)) {
            xmlWriter.writeElementString("VERSION", "05");
        } else {
            xmlWriter.writeElementString("VERSION", "04");
        }
        xmlWriter.writeElementString("DATA_TYPE", "2");
        xmlWriter.writeElementString("LEVEL", "5");
        xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("USER_PASS", actItem.userFlag);

        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        xmlWriter.writeEndElement();
    }

    protected void writeContractCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("INFO");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        xmlWriter.writeElementString("VERSION", "04");
        xmlWriter.writeElementString("DATA_TYPE", "2");
        xmlWriter.writeElementString("LEVEL", "5");

        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("USER_PASS", actItem.userFlag);

        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        //xmlWriter.writeElementClosed("SIGNED_MSG");
        xmlWriter.writeEndElement();//</INFO>
    }

    protected void writeJFBCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("HEAD");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        xmlWriter.writeElementString("VERSION", "02");
        xmlWriter.writeElementString("LEVEL", "5");
        xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
        xmlWriter.writeElementString("SUBMIT_TIME", Format.DateTime14Format.format(new Date()));
        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        xmlWriter.writeEndElement();
    }

    protected void writeRealTimeCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("INFO");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        xmlWriter.writeElementString("VERSION", "03");
        xmlWriter.writeElementString("DATA_TYPE", "2");
        xmlWriter.writeElementString("LEVEL", "9");

        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("USER_PASS", actItem.userFlag);

        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        xmlWriter.writeEndElement();
    }

    protected void writeBatBillCommonHeader(XmlTextWriter xmlWriter, AllInPay02Header bankHeader, ActSetItem actItem) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.TRX_CODE)) {
            throw new Exception("未赋值TRX_CODE");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.REQ_SN)) {
            throw new Exception("未赋值REQ_SN");
        }
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("AIPG");
        xmlWriter.writeStartElement("HEAD");
        xmlWriter.writeElementString("TRX_CODE", bankHeader.TRX_CODE);
        xmlWriter.writeElementString("VERSION", "03");
        xmlWriter.writeElementString("LEVEL", "9");
        xmlWriter.writeElementString("MERCHANT_ID", actItem.merchantId);
        xmlWriter.writeElementString("SUBMIT_TIME", Format.DateTime14Format.format(new Date()));
        xmlWriter.writeElementString("USER_NAME", actItem.userCode);
        xmlWriter.writeElementString("REQ_SN", bankHeader.REQ_SN);
        xmlWriter.writeEndElement();
    }

    protected String signMessage(String p_toSignStr, ActSetItem actItem, StringBuilder p_sbLog) {
        try {
            byte[] toSignByte = p_toSignStr.getBytes(getCharset());
            byte[] signResult = SignVerifyHelper.signData(toSignByte, "PKCS12", "SHA1withRSA", actItem.ownKeyStorePath, actItem.ownKeyPassword, p_sbLog);
            if (signResult != null && p_sbLog.length() == 0) {
                byte[] sign_asc = new byte[signResult.length * 2];
                hex2Ascii(signResult.length, signResult, sign_asc);
                return new String(sign_asc, getCharset());
            } else {
                this.WriteBankLogLn("签名失败：" + p_sbLog.toString());
                return null;
            }
        } catch (Exception ex) {
            this.WriteBankLogLn(ex);
            p_sbLog.append(ex.getMessage());
        }

        return null;
    }

    private void hex2Ascii(int len, byte[] data_in, byte[] data_out) {
        byte[] temp1 = new byte[1];
        byte[] temp2 = new byte[1];
        int i = 0;
        for (int j = 0; i < len; ++i) {
            temp1[0] = data_in[i];
            temp1[0] = (byte) (temp1[0] >> 4);
            temp1[0] = (byte) (temp1[0] & 0xF);
            temp2[0] = data_in[i];
            temp2[0] = (byte) (temp2[0] & 0xF);
            if ((temp1[0] >= 0) && (temp1[0] <= 9))
                data_out[j] = (byte) (temp1[0] + 48);
            else if ((temp1[0] >= 10) && (temp1[0] <= 15)) {
                data_out[j] = (byte) (temp1[0] + 87);
            }

            if ((temp2[0] >= 0) && (temp2[0] <= 9))
                data_out[(j + 1)] = (byte) (temp2[0] + 48);
            else if ((temp2[0] >= 10) && (temp2[0] <= 15))
                data_out[(j + 1)] = (byte) (temp2[0] + 87);

            j += 2;
        }
    }

    /**
     * 统一下单数据提交
     *
     * @param params 请求MAP
     * @param url    请求地址
     * @return 响应JSON
     * @throws Exception
     */
    protected String sendUnifiedToBank(TreeMap<String, String> params, String url) throws Exception {
        WriteBankLogLn2("通联交易服务地址:" + url);

        String reqPostData = getUnifiedOrderPostData(params);
        WriteBankLogLn2("发送通联请求数据:\r\n" + reqPostData);

        HttpConnectionUtil http = new HttpConnectionUtil(url);
        http.init();
        byte[] bys = http.postParams(reqPostData, true);

        String result = new String(bys, "UTF-8");
        WriteBankLogLn2("通联响应数据:\r\n" + result);

        return result;
    }

    protected String getUnifiedOrderPostData(TreeMap<String, String> params) {
        StringBuilder outBuf = new StringBuilder();
        boolean isNotFirst = false;

        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (isNotFirst)
                outBuf.append('&');
            isNotFirst = true;
            try {
                outBuf.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        return outBuf.toString();
    }

    protected String sendPayRecStatement(String p_url, String p_reqData) throws Exception {
        StringBuffer srcStr = new StringBuffer();
        //URL url = null;

        try {
            //url = new URL();
            int timeout = this.getReadTimeout(120);
            WriteBankLogLn2("超时时间:" + timeout + "毫秒");
            WriteBankLogLn2("请求链接:" + p_url + "?" + p_reqData);
            HttpURLConnection httpConn = new AllInPay02Base().getHttpsURLConnection(p_url + "?" + p_reqData);
            httpConn.setReadTimeout(timeout);
            httpConn.connect();

            BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
            String lines;
            while ((lines = reader.readLine()) != null) {
                if (lines.length() > 0) {
                    srcStr.append(lines + "\r\n");
                }
            }
            reader.close();
            httpConn.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return srcStr.toString();
    }

    protected String[] sendToBank(String p_reqStr, ActSetItem actItem) throws Exception {
        String[] retStr = new String[]{"", ""};

        String serverUrl = bankFront.serverURL;
        if (StringHelper.hasAnyChar(actItem.serverURL)) {
            serverUrl = actItem.serverURL;
        }
        WriteBankLogLn("2.提交银行的地址：" + serverUrl);
        StringBuilder tmpSb = new StringBuilder();
        String signResult = signMessage(p_reqStr, actItem, tmpSb);
        if (signResult != null && tmpSb.length() == 0) {
            int indexIns = p_reqStr.indexOf("</INFO>");
            StringBuilder tmpSbPck = new StringBuilder();
            tmpSbPck.append(p_reqStr.substring(0, indexIns));
            tmpSbPck.append("<SIGNED_MSG>");
            tmpSbPck.append(signResult);
            tmpSbPck.append("</SIGNED_MSG>");
            tmpSbPck.append(p_reqStr.substring(indexIns));
            WriteBankLogStep2(tmpSbPck);
            WebRequest tmpWebRequest = new WebRequest(serverUrl, this.bankFront, this.sbLog);
            tmpWebRequest.setConnectTimeout(getReadTimeout(120));
            //tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            tmpWebRequest.setRequestProperty("connection", "Close");
            byte[] tmpUpBytes = tmpSbPck.toString().getBytes(getCharset());
            retStr = tmpWebRequest.upload(tmpUpBytes, getCharset());
            WriteBankLogStep3(retStr[1]);
            if (retStr[0].length() == 0) {
                int tmpIndex = retStr[1].indexOf("<");
                if (tmpIndex > 0) {
                    retStr[1] = retStr[1].substring(tmpIndex);
                }
            }
        } else {
            retStr[0] = FailCode.E9981;
            retStr[1] = "签名失败：" + tmpSb.toString();
        }
        return retStr;
    }

    protected String[] sendContractToBank(String p_reqStr, ActSetItem actItem) throws Exception {
        String[] retStr = new String[]{"", ""};
        String submitUrl = bankFront.getUrl("contractSubmit");
        WriteBankLogLn("2.提交银行的地址：" + submitUrl);
        StringBuilder tmpSb = new StringBuilder();
        String signResult = signMessage(p_reqStr, actItem, tmpSb);
        if (signResult != null && tmpSb.length() == 0) {
            int indexIns = p_reqStr.indexOf("</INFO>");
            StringBuilder tmpSbPck = new StringBuilder();
            tmpSbPck.append(p_reqStr.substring(0, indexIns));
            tmpSbPck.append("<SIGNED_MSG>");
            tmpSbPck.append(signResult);
            tmpSbPck.append("</SIGNED_MSG>");
            tmpSbPck.append(p_reqStr.substring(indexIns));
            WriteBankLogStep2(tmpSbPck);
            WebRequest tmpWebRequest = new WebRequest(submitUrl, this.bankFront, this.sbLog);
            tmpWebRequest.setConnectTimeout(getReadTimeout(120));
            //tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            tmpWebRequest.setRequestProperty("connection", "Close");
            byte[] tmpUpBytes = tmpSbPck.toString().getBytes(getCharset());
            retStr = tmpWebRequest.upload(tmpUpBytes, getCharset());
            WriteBankLogStep3(retStr[1]);
            if (retStr[0].length() == 0) {
                int tmpIndex = retStr[1].indexOf("<");
                if (tmpIndex > 0) {
                    retStr[1] = retStr[1].substring(tmpIndex);
                }
            }
        } else {
            retStr[0] = FailCode.E9981;
            retStr[1] = "签名失败：" + tmpSb.toString();
        }
        return retStr;
    }

    protected String[] sendJFBToBank(String p_reqStr, ActSetItem actItem, String reqSeqNo) throws Exception {
        String[] retStr = new String[]{"", ""};

        String serverUrl = bankFront.getUrl("JFBRequest") + "?MERCHANT_ID=" + actItem.merchantId + "&REQ_SN=" + reqSeqNo;
        WriteBankLogLn2("2.提交银行的地址：" + serverUrl);
        StringBuilder tmpSb = new StringBuilder();
        String signResult = new AIPGSignature().signMsg(p_reqStr, actItem.ownKeyStorePath, actItem.ownKeyPassword);
        if (signResult != null && tmpSb.length() == 0) {
            StringBuilder tmpSbPck = new StringBuilder();
            tmpSbPck.append(p_reqStr);
            tmpSbPck.append("<SIGNED_MSG>");
            tmpSbPck.append(signResult);
            tmpSbPck.append("</SIGNED_MSG>");
            WriteBankLogStep2(tmpSbPck);
            System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

            retStr[1] = HttpUtil.post(tmpSbPck.toString(), serverUrl);
            WriteBankLogStep3(retStr[1]);
        } else {
            retStr[0] = FailCode.E9981;
            retStr[1] = "签名失败：" + tmpSb.toString();
        }
        return retStr;
    }

    protected String[] sendBillToBank(String p_reqStr, ActSetItem actItem, String reqSeqNo) throws Exception {
        String[] retStr = new String[]{"", ""};

        String serverUrl = actItem.qryStatementURL + "?MERCHANT_ID=" + actItem.merchantId + "&REQ_SN=" + reqSeqNo;
        WriteBankLogLn("2.提交银行的地址：" + serverUrl);
        StringBuilder tmpSb = new StringBuilder();
        String signResult = new AIPGSignature().signMsg(p_reqStr, actItem.ownKeyStorePath, actItem.ownKeyPassword);
        if (signResult != null && tmpSb.length() == 0) {
            StringBuilder tmpSbPck = new StringBuilder();
            tmpSbPck.append(p_reqStr);
            tmpSbPck.append("<SIGNED_MSG>");
            tmpSbPck.append(signResult);
            tmpSbPck.append("</SIGNED_MSG>");
            WriteBankLogStep2(tmpSbPck);
            System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");

            retStr[1] = HttpUtil.post(tmpSbPck.toString(), serverUrl);
            WriteBankLogStep3(retStr[1]);
        } else {
            retStr[0] = FailCode.E9981;
            retStr[1] = "签名失败：" + tmpSb.toString();
        }
        return retStr;
    }

    /**
     * 将MAP转换为post请求串
     *
     * @param returns
     * @param paramId
     * @param paramValue
     * @return
     */
    public String appendParam(String returns, String paramId, String paramValue) {
        if (returns != "") {
            if (paramValue != "") {
                returns += "&" + paramId + "=" + paramValue;
            }
        } else {
            if (paramValue != "") {
                returns = paramId + "=" + paramValue;
            }
        }

        return returns;
    }

    /**
     * 生成post请求数据
     *
     * @param paramData
     * @return
     */
    protected String getPostData(NameValuePair[] paramData) {
        String postData = "";

        for (NameValuePair param : paramData) {
            if (postData.length() > 0) {
                postData += "&";
            }

            postData += param.getName() + "=" + param.getValue();
        }

        return postData;
    }

    /**
     * 获取验签原始数据
     *
     * @param p_reqStr 待验签原始串
     * @return 验签结果
     */
    protected TreeMap<String, String> getParams(String p_reqStr) {
        TreeMap<String, String> map = new TreeMap<String, String>();

        String[] postArrays = p_reqStr.split("&");
        for (String postArray : postArrays) {
            String key = postArray.split("=")[0];
            String value = postArray.split("=")[1];

            map.put(key, value);
        }

        return map;
    }

    private static boolean isTrusted = false;

    public HttpURLConnection getHttpsURLConnection(String p_addr) throws Exception {

        try {
            URL url;
            if (p_addr.contains("https://")) {
                //url = new URL(null, p_addr, new com.sun.net.ssl.internal.www.protocol.https.Handler());
                if (isTrusted == false) {
                    HttpsHandler.trustAllHttpsCertificates();
                    isTrusted = true;
                }
                HostnameVerifier hv = new HostnameVerifier() {
                    public boolean verify(String urlHostName, SSLSession session) {
                        return true;
                    }
                };
                HttpsURLConnection.setDefaultHostnameVerifier(hv);
                url = new URL(null, p_addr, new sun.net.www.protocol.https.Handler());
            } else {
                url = new URL(p_addr);
            }
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();

            return httpConnection;

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return null;
    }

    public class MyX509TrustManager implements X509TrustManager {

        /**
         * 该方法体为空时信任所有客户端证书
         *
         * @param chain
         * @param authType
         * @throws CertificateException
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        /**
         * 该方法体为空时信任所有服务器证书
         *
         * @param chain
         * @param authType
         * @throws CertificateException
         */

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws java.security.cert.CertificateException {

        }

        @Override
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws java.security.cert.CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    /**
     * 验签
     *
     * @param src
     * @param mac
     * @return
     */
    public boolean verifySign(String src, String mac, ActSetItem actItem) {
        try {
            src = SecurityUtil.MD5Encode(src);
            boolean result = SecurityUtil.verifyByRSA(actItem.oppCertFilePath, src.getBytes(getCharset()), Base64.decodeBase64(mac));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean verifySign(String src, String mac, String p_certFilePath) {
        try {
            src = SecurityUtil.MD5Encode(src);
            boolean result = SecurityUtil.verifyByRSA(p_certFilePath, src.getBytes(getCharset()), Base64.decodeBase64(mac));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String convertErrToAts(String p_respCode) {
        int i = Integer.parseInt(p_respCode);

        switch (i) {
            case 1:
                return "系统繁忙.请稍候............";
            case 2:
                return "请传入有效的商户号,结算日期,signMsg";
            case 3:
                return "结算日期格式错误(格式为 yyyy-MM-dd)";
            case 4:
                return "商户号不存在或者 MD5key 没有设置";
            case 5:
                return "摘要信息验证有误";
            case 6:
                return "没有相应的对账信息";
            default:
                break;
        }

        return null;
    }

    /**
     * 返回HTTP字符串转MAP
     *
     * @param
     * @return
     */
    public static Map<String, String> convertToMap(String srcStr) {
        Map<String, String> params = new HashMap<String, String>();

        String[] nodes = srcStr.split("&");
        for (String node : nodes) {
            int index = node.indexOf("=");

            String key = node.substring(0, index);
            String value = node.substring(index + 1);

            params.put(key, value);
        }

        return params;
    }

    protected String getSignStr(Map<String, String> map) {
        Map<String, String> signMap = new HashMap<String, String>();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();

            if (!"sign".equals(name)) {
                signMap.put(name, value);
            }
        }

        // Map排序
        signMap = SortHelper.sortMapByName(signMap);

        // Map转HTTP字符串
        String signStr = "";
        for (String key : signMap.keySet()) {
            signStr += "&" + key + "=" + signMap.get(key);
        }
        signStr = signStr.substring(1);

        return signStr;
    }

    protected String signWithMD5(Map<String, String> map) throws IOException {
        String signData = getSignStr(map);
        String tmpSign = SybUtil.md5(signData.getBytes(getCharset("UTF-8", "pos")));
        return tmpSign;
    }

    public Map<String, String> removeHead(Map<String, String> tmpMapParams) {
        tmpMapParams.remove("BankCode");
        tmpMapParams.remove("TransType");
        tmpMapParams.remove("CommandCode");
        tmpMapParams.remove("Entity");
        return tmpMapParams;
    }

    protected String getSignData(Map<String, String> mapParams) {
        Map<String, String> signMap = new HashMap<String, String>();

        for (Map.Entry<String, String> entry : mapParams.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();

            if (StringHelper.hasAnyChar(value)) {
                signMap.put(name, value);
            }
        }

        // Map排序
        signMap = SortHelper.sortMapByName(signMap);

        // Map转HTTP字符串
        String signStr = "";
        for (String key : signMap.keySet()) {
            signStr += "&" + key + "=" + signMap.get(key);
        }
        signStr = signStr.substring(1);

        return signStr;
    }

    /**
     * 收银宝网关支付下单签名
     */
    public String sign(TreeMap<String, String> params, String key) {
        params.put("key", key);
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() != null && entry.getValue().length() > 0) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        WriteBankLogLn2("待签名明文数据:\r\n" + sb.toString());
        WriteBankLogLn2("签名使用密钥为："+ key);
        String sign = md5(sb.toString()).toUpperCase();
        WriteBankLogLn2("签名后密文数据:" + sign);
        params.remove("key");
        return sign;
    }

    /**
     * Map转换为String
     */
    public String convertMapToStr(Map<String, String> params) {
        String reqStr = "";
        for (String key : params.keySet()) {
            if (!key.equals("")) {
                if (reqStr.length() > 0) {
                    reqStr += "&";
                }
                reqStr += key + "=" + params.get(key);
            }
        }
        return reqStr;
    }

    /**
     * 下载对账单到本地并读取压缩包中业务明细文件内容
     *
     * @throws Exception
     */
    protected void smsGet(String p_url, String filePath) throws Exception {
        URL url = null;
        HttpURLConnection httpUrlConnection = null;
        InputStream fis = null;
        FileOutputStream fos = null;

        try {
            if (p_url.contains("https://")) {
                url = new URL(null, p_url, new sun.net.www.protocol.https.Handler());
            } else {
                url = new URL(p_url);
            }
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setConnectTimeout(5 * 1000);
            httpUrlConnection.setDoInput(true);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setUseCaches(false);
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setRequestProperty("Charsert", "GBK");
            httpUrlConnection.connect();
            fis = httpUrlConnection.getInputStream();
            byte[] temp = new byte[1024];
            int b;
            fos = new FileOutputStream(new File(filePath));
            while ((b = fis.read(temp)) != -1) {
                fos.write(temp, 0, b);
            }
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                if (fos != null) fos.close();
                if (fis != null) fis.close();
                if (httpUrlConnection != null) httpUrlConnection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return;
    }

    /**
     * 下载对账单到本地并读取压缩包中业务明细文件内容(.csv)
     */
    protected SendBankRespose csvGet(String p_url, String filePath, ReqQryStatement p_reqQrySttm) {
        SendBankRespose retResp = new SendBankRespose();

        URL url = null;
        HttpURLConnection httpUrlConnection = null;
        InputStream fis = null;
        FileOutputStream fos = null;
        Scanner scanner = null;

        try {

            String fileCharset = getBankConfig().getCharset("UTF-8", "SYB");

            url = new URL(p_url);
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setConnectTimeout(50 * 1000);
            httpUrlConnection.setDoInput(true);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setUseCaches(false);
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setRequestProperty("Charset", "UTF-8");
            httpUrlConnection.connect();
            fis = httpUrlConnection.getInputStream();
            byte[] temp = new byte[1024];
            int b;
            fos = new FileOutputStream(new File(filePath));
            while ((b = fis.read(temp)) != -1) {
                fos.write(temp, 0, b);
                fos.flush();
            }

            StringBuilder content = new StringBuilder();
            ZipFile zip = new ZipFile(filePath, fileCharset);
            @SuppressWarnings("unchecked")
            Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.getEntries();

            ZipEntry ze;
            while (entries.hasMoreElements()) {
                ze = entries.nextElement();
                WriteBankLogLn("账单解压后文件列表:" + ze.getName());
                if (ze.getName().contains(p_reqQrySttm.actNum) && ze.getName().contains(".csv")) {
                    scanner = new Scanner(zip.getInputStream(ze), fileCharset);
                    while (scanner.hasNextLine()) {
                        content.append(scanner.nextLine() + "\n");
                    }
                }
            }
            zip.close();

            retResp.retMessage = content.toString();
        } catch (IOException e) {
            retResp.connState = FailCode.E9999;
            retResp.retMessage = e.getMessage();
            retResp.appendLog(e);
            return retResp;
        } finally {
            try {
                if (fos != null) fos.close();
                if (fis != null) fis.close();
                if (scanner != null) scanner.close();
                if (httpUrlConnection != null) httpUrlConnection.disconnect();
            } catch (IOException e) {
                this.WriteBankLogLn(e);
            }
        }

        return retResp;
    }
}
